package com.yonyou.gmmc.service.points.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.marketing.common.dto.MessageDto;
import org.marketing.common.dto.points.CustomerPointsDto;
import org.marketing.common.event.BizEvent;
import org.marketing.common.event.EventActivityInfoReadDTO;
import org.marketing.common.event.EventPointsChangedDTO;
import org.marketing.common.event.ExpirePointsDTO;
import org.marketing.common.event.enums.EventConstant;
import org.marketing.common.event.enums.EventConstant.EventBizStep;
import org.marketing.common.event.enums.EventConstant.EventBizType;
import org.marketing.common.util.MapConverUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.yonyou.gmmc.common.annotation.CatTransaction;
import com.yonyou.gmmc.common.service.BaseService;
import com.yonyou.gmmc.service.points.constant.PointsConstant;
import com.yonyou.gmmc.service.points.dao.TmTpOrderStatusLogMapper;
import com.yonyou.gmmc.service.points.dao.TtCustomerPointsLogMapper;
import com.yonyou.gmmc.service.points.dao.TtCustomerPointsMapper;
import com.yonyou.gmmc.service.points.dao.TtEventHandleLogMapper;
import com.yonyou.gmmc.service.points.eventhandle.AbstractEventHandle;
import com.yonyou.gmmc.service.points.eventhandle.EventHandleFactory;
import com.yonyou.gmmc.service.points.eventhandle.HandleResult;
import com.yonyou.gmmc.service.points.eventhandle.RegisterSigninEventHandler;
import com.yonyou.gmmc.service.points.exception.PointsException;
import com.yonyou.gmmc.service.points.model.TmTpOrderStatusLog;
import com.yonyou.gmmc.service.points.model.TtCustomerPoints;
import com.yonyou.gmmc.service.points.model.TtCustomerPointsLog;
import com.yonyou.gmmc.service.points.model.TtEventHandleLog;

import tk.mybatis.mapper.entity.Example;

@Service
@Primary
@Transactional
public class PointsPayService extends BaseService {

    private static Logger     logger = LoggerFactory.getLogger(RegisterSigninEventHandler.class);

    @Autowired
    private TtCustomerPointsMapper    ttCustomerPointsMapper;

    @Autowired
    private TtCustomerPointsLogMapper ttCustomerPointsLogMapper;

    @Autowired
    private TtEventHandleLogMapper    ttEventHandleLogMapper;

    @Autowired
    private TmTpOrderStatusLogMapper  tmTpOrderStatusLogMapper;

    @Autowired
    private BaseService               eventService;

    /**
     * 处理积分的时间
     * 
     * @param event
     * @return 返回是否处理完毕，true完毕，false可以重试
     */
    public HandleResult HandlePointsEvent(BizEvent event) {
        // 创建处理的对象
        logger.info(">>>>>>>1");
        AbstractEventHandle handle = EventHandleFactory.createHandle(event);
        logger.info(">>>>>>>2" + handle.toString());
        // 处理
        logger.info(">>>>>>>3");
        HandleResult result = handle.handleing(event);
        logger.info(">>>>>>>4");
        return result;

    }

    /**
     * 发放积分到用户
     * 
     * @param points 变化的分数
     * @param userId 用户
     * @param reason 原因
     * @param keyCode 关键业务字段
     * @param bizStep 业务节点 剩下的是其他预留的code
     * @return
     */
    @CatTransaction(type = "积分相关", name = "发送积分到用户")
    public int payPointsToUser(Long points, int userId, String phone, String reason, String keyCode, int bizStep,
                               String... bc) throws PointsException {
        TtCustomerPoints userPointsNow = userPointsExist(new Long(userId), null);
        int updateCount = 0;
        if (userPointsNow != null) {
            // 更新的条件
            Example example = new Example(TtCustomerPoints.class);
            example.createCriteria().andCondition("user_id=", userId).andCondition("version=",
                                                                                   userPointsNow.getVersion());

            // 更新
            TtCustomerPoints userPointsV = new TtCustomerPoints();
            userPointsV.setPointsNum(userPointsNow.getPointsNum() + points);
            userPointsV.setPhone(phone);
            userPointsV.setVersion(userPointsNow.getVersion() + 1);
            userPointsV.setUpdateBy(PointsConstant.OPT_USER);
            userPointsV.setUpdateDate(new Date());
            updateCount = ttCustomerPointsMapper.updateByExampleSelective(userPointsV, example);
            if (updateCount != 1) {
                throw new PointsException(PointsException.POINTS_CHANGED, "更新条数异常，一般是数据被其他线程修改");
            }
        } else {
            userPointsNow = new TtCustomerPoints();
            userPointsNow.setPointsNum(0L);// 设置为0
            updateCount = insertUserPoints(new Long(userId), phone, points);
            if (updateCount != 1) {
                throw PointsException.DB_INSERT_RESULT_0;
            }
        }
        //2017-09-13 重新设置积分变动原因
        if(bizStep==10051002){
            String name = ttCustomerPointsMapper.selectRecommandName(keyCode);
            reason = "推荐"+ name +"购车线索积分有效";
        }else if(bizStep==10051001){
            String name = ttCustomerPointsMapper.selectRecommandName(keyCode);
            reason = "推荐"+ name +"购车下单成功";
        }else if(bizStep==10091001){
            String name = ttCustomerPointsMapper.selectQuestionnaireName(keyCode);
            reason = "问卷"+ name +"提交";
        }
        // 新增积分变动的log
        this.insertPointsLog(userPointsNow.getPointsNum(), points, userId, phone, reason, keyCode, bizStep, bc);

        try {
            logger.info("推送积分变更事件到MQ");
            // 具体业务参数
            EventPointsChangedDTO eventDate = new EventPointsChangedDTO();
            eventDate.setAfterPoints(userPointsNow.getPointsNum() + points);
            eventDate.setBeforePoints(userPointsNow.getPointsNum());
            eventDate.setChangePoints(points);
            eventDate.setReason(reason);
            eventDate.setUserId(userId);
            // 业务事件
            BizEvent bizEvent = new BizEvent();
            bizEvent.setEventKey(keyCode + new Date().getTime());
            bizEvent.setEventBizType(EventConstant.EventBizType.COMMON);
            bizEvent.setEventBizStep(EventConstant.EventBizStep.COMMON_POINTS_CHANGED);
            bizEvent.setEventData(MapConverUtil.PO2Map(eventDate));
            logger.info(bizEvent.toString());
            String returnString = this.sendEvent2MQ(bizEvent);

            logger.info("推送积分变更事件到MQ结束:" + returnString);

            logger.info("发送消息通知");
            String potentialUserId = ttCustomerPointsMapper.selectPotential(userId);
            MessageDto dto = new MessageDto();
            if(eventDate.getChangePoints()>0){
            	dto.setMessageContent("您的积分因为"+eventDate.getReason()+"+"+eventDate.getChangePoints()+"分，当前积分："+eventDate.getAfterPoints()+"分，详情请至个人中心-我的积分查看。");
            }else{
            	dto.setMessageContent("您的积分因为"+eventDate.getReason()+eventDate.getChangePoints()+"分，当前积分："+eventDate.getAfterPoints()+"分，详情请至个人中心-我的积分查看。");
            }
            dto.setMessageTitle("积分变动");
            dto.setMessageType("40011005");
            dto.setUserId(Long.valueOf(potentialUserId));
            BizEvent et = new BizEvent();
            et.setEventBizType(EventBizType.SEND_MESSAGE);
            et.setEventBizStep(EventBizStep.SEND_MESSAGE_NOTICE);
            et.setEventKey("MESSAGE:" + dto.getUserId() + ":" + new Date().getTime());
            et.setEventData(MapConverUtil.PO2Map(dto));
            String s = eventService.sendEvent2MQ(et);
            logger.info("发送消息通知，MQ返回结果>>>>>>>>>>>>>>>>>>>>" + s);
        } catch (Exception e) {
            logger.error("消息未发送成功，但是只是消息异动的通知，不影响业务流程", e);
        }
        return updateCount;
    }

    /**
     * 插入更新的日志
     * 
     * @param beforePoing
     * @param points
     * @param userId
     * @param phone
     * @param reason
     * @param keyCode
     * @param bizStep
     * @param bc
     * @return
     */
    public int insertPointsLog(Long beforePoing, Long points, int userId, String phone, String reason, String keyCode,
                               int bizStep, String... bc) {
        // 记录发放积分的log
        logger.info("开始记录积分变动的log");
        TtCustomerPointsLog log = new TtCustomerPointsLog();
        log.setUserId(new Long(userId));
        log.setChangeBefore(beforePoing);
        log.setChangeAfter(beforePoing + points);
        log.setChangePoints(points);
        log.setChangeReason(reason);
        log.setKeyCode(keyCode);
        log.setChangeType(new Long(bizStep));
        log.setCreateBy(PointsConstant.OPT_USER);
        log.setCreateDate(new Date());
        if (bc != null) {
            if (bc.length == 1) {
                log.setBc1(bc[0]);
            } else if (bc.length == 2) {
                log.setBc1(bc[0]);
                log.setBc1(bc[1]);
            } else if (bc.length == 3) {
                log.setBc1(bc[0]);
                log.setBc2(bc[1]);
                log.setBc3(bc[2]);
            } else {
                logger.warn("记录log时，未传入或传入超过3条业务code");
            }
        }

        return ttCustomerPointsLogMapper.insertSelective(log);
    }

    /**
     * 判断用户是否存在积分
     * 
     * @return
     */
    public TtCustomerPoints userPointsExist(Long userId, String phone) {
        TtCustomerPoints userPoints = new TtCustomerPoints();
        userPoints.setPhone(phone);
        userPoints.setUserId(userId);
        // 查询数量
        return ttCustomerPointsMapper.selectOne(userPoints);
    }

    /**
     * 新增用户积分记录
     * 
     * @param userId
     * @param phone
     * @param pointsNum
     * @return
     */
    public int insertUserPoints(Long userId, String phone, Long pointsNum) {
        logger.info("开始用户积分的log");
        TtCustomerPoints userPoints = new TtCustomerPoints();
        userPoints.setPhone(phone);
        userPoints.setUserId(userId);
        userPoints.setPointsNum(pointsNum);
        userPoints.setVersion(0);// 默认是1
        userPoints.setCreateBy(PointsConstant.OPT_USER);
        userPoints.setCreateDate(new Date());
        return ttCustomerPointsMapper.insertSelective(userPoints);
    }

    /**
     * 新增事件处理记录
     * 
     * @param event
     * @return
     */
    public int insertHandleLog(BizEvent event) {
        TtEventHandleLog log = new TtEventHandleLog();
        log.setBcId(event.getEventBizType().getCodeLong());
        log.setTcId(event.getEventBizStep().getCodeLong());
        log.setEventKey(event.getEventKey());
        if (event.getEventData().toString().length() > 3500) {
            log.setEventData(event.getEventData().toString().substring(0, 3500));
        } else {
            log.setEventData(event.getEventData().toString());
        }
        log.setCreateBy(PointsConstant.OPT_USER);
        log.setCreateDate(new Date());
        return ttEventHandleLogMapper.insertSelective(log);
    }

    /**
     * 查询数量
     * 
     * @param event
     * @return
     */
    public int queryEventNum(BizEvent event) {
        TtEventHandleLog log = new TtEventHandleLog();
        log.setBcId(event.getEventBizType().getCodeLong());
        log.setTcId(event.getEventBizStep().getCodeLong());
        log.setEventKey(event.getEventKey());
        // 为了和其他服务共用这个表，增加一个处理人条件，同一个事件可以被多个服务监听去处理
        log.setCreateBy(PointsConstant.OPT_USER);
        return ttEventHandleLogMapper.selectCount(log);
    }

    /**
     * 查询积分
     * 
     * @param userid
     * @return
     * @throws ParseException
     */
    public List<CustomerPointsDto> getCustomerPoints(String openId, Long flag) throws ParseException {

        List<CustomerPointsDto> dolist = new ArrayList<>();
        logger.info("查询积分开始明细，openId=" + openId + ",flag=" + flag);
        if (flag == 1) {
            // 查询用户积分
            logger.info("flag=1查询用户个人积分");
            dolist = ttCustomerPointsLogMapper.getCustomerPoints(openId);
            logger.info("flag=1查询用户个人积分结束，dolist=" + dolist.size());
        } else if (flag == 2) {
            // 查询经销商积分
            logger.info("flag=2查询用户经销商积分");
            dolist = ttCustomerPointsLogMapper.getDealerPointLog(openId);
            logger.info("flag=2查询用户经销商积分结束，dolist=" + dolist.size());
        }
        for (int i = 0; i < dolist.size(); i++) {
            CustomerPointsDto element = new CustomerPointsDto();
            element = dolist.get(i);
            Date d = element.getRegisterDate();
            logger.info("积分产生日期：" + d);
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            String s = df.format(new Date(d.getTime() + (long) 730 * 24 * 60 * 60 * 1000));
            Date date = df.parse(s);
            logger.info("积分过期日期：" + date);
            element.setRegisterDate(date);
            dolist.set(i, element);
        }
        return dolist;

    }

    /**
     * 查询个人总积分
     * 
     * @param userId
     * @return
     */
    public List<CustomerPointsDto> getCountpoint(String openId) {

        logger.info("查询用户个人积分，openId=" + openId);
        List<CustomerPointsDto> dolist = ttCustomerPointsLogMapper.getCountpoint(openId);
        logger.info("查询用户个人积分结束，dolist=" + dolist);
        // 查询经销商积分
        logger.info("查询用户经销商积分");
        CustomerPointsDto customerPointsDto = ttCustomerPointsLogMapper.getDealerPoint(openId);
        if (customerPointsDto != null) {
            logger.info("添加用户经销商积分：" + customerPointsDto);
            dolist.add(customerPointsDto);
        }
        return dolist;

    }

    /**
     * @author Administrator
     * @date 2017年4月21日
     * @param thisEventData
     * @return
     */
    public int getCustomerLog(EventActivityInfoReadDTO thisEventData) {
        // 创建日期对象
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String date = sdf.format(d);
        logger.info("创建Example");
        Example ex = new Example(TtCustomerPointsLog.class);
        ex.createCriteria().andCondition("USER_ID=",
                                         thisEventData.getUserId()).andCondition("CHANGE_TYPE=",
                                                                                 PointsException.ACTIVITY_INFO_READ).andCondition("to_char(create_date,'YYYY-MM-DD')=",
                                                                                                                                  date);
        // int i = ttCustomerPointsLogMapper.selectCountByExample(ex);
        int i = 0;
        List<TtCustomerPointsLog> list = ttCustomerPointsLogMapper.selectByExample(ex);
        if (list.size() == 0) {
            logger.info("该用户今日暂未获取阅读积分");
        } else {
            Long b = 0L;
            for (int a = 0; a < list.size(); a++) {
                b = b + list.get(a).getChangePoints();
            }
            i = b.intValue();
        }
        return i;
    }

    /**
     * 记录订单状态变更日志
     * 
     * @author Administrator
     * @date 2017年5月9日
     * @param isPay
     * @param thirdOrder
     * @return
     */
    public int updateOrderStatusLog(boolean isPay, String thirdOrder) {
        int i = 0;
        String orderStatusBefore = PointsConstant.BEFORE_PAY;
        String orderStatusAfter = "";
        if (isPay) {
            logger.info("扣分成功");
            orderStatusAfter = PointsConstant.PAY_SUCCESS;
        } else {
            logger.info("扣分失败");
            orderStatusAfter = PointsConstant.PAY_FAILED;
        }
        TmTpOrderStatusLog record = new TmTpOrderStatusLog();
        record.setCreateBy(PointsConstant.OPT_USER.longValue());
        logger.info("更新人>>>>>>>>>>>>>" + record.getCreateBy());
        record.setCreateDate(new Date());
        logger.info("更新时间>>>>>>>>>>>>>" + record.getCreateDate());
        record.setOrderStatusBefore(Long.valueOf(orderStatusBefore));
        logger.info("更新前状态>>>>>>>>>>>>>" + record.getOrderStatusBefore());
        record.setOrderStatusAfter(Long.valueOf(orderStatusAfter));
        logger.info("更新后状态>>>>>>>>>>>>>" + record.getOrderStatusAfter());
        logger.info("创建Example");
        Example ex = new Example(TmTpOrderStatusLog.class);
        ex.createCriteria().andCondition("THIRD_ORDER=", thirdOrder);
        i = tmTpOrderStatusLogMapper.updateByExampleSelective(record, ex);
        logger.info("更新了" + i + "条");
        return i;
    }

    public Map<String,Object> PointsExpire(String date){
        logger.info("传入的当前时间为："+date);
        Map<String,Object> result = new HashMap<String,Object>();
        logger.info("查询出已到期的积分");
        List<TtCustomerPoints> list = ttCustomerPointsMapper.selectExpire(date);
        logger.info("今日有"+list.size()+"个已过期积分用户");
        //发送积分过期扣分事件
        for(int a = 0;a<list.size();a++){
            ExpirePointsDTO dto = new ExpirePointsDTO();
            dto.setUserId(list.get(a).getUserId().intValue());
            dto.setPhone(list.get(a).getPhone());
            dto.setPointsNum(list.get(a).getPointsNum());
            BizEvent event = new BizEvent();
            event.setEventBizType(EventBizType.POINTS_EXPIRE);
            event.setEventBizStep(EventBizStep.POINTS_EXPIRE_DEDUCTED);
            event.setEventKey("JFGQ:"+new Date().getTime());
            event.setEventData(MapConverUtil.PO2Map(dto));
            String s = "";
            try {
                s = eventService.sendEvent2MQ(event);
                logger.info("MQ返回结果>>>>>>>>>>>>>>>>>>>>" + s);
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }
        return result;
    }
    
    /**
    * 查询积分兑换记录
    * @author Administrator
    * @date 2017年12月1日
    * @param openId
    * @return
    */
    public Map<String,Object> conversionLog(String openId){
        Map<String, Object> result = new HashMap<String, Object>();
        result = ttCustomerPointsLogMapper.conversionLog(openId);
        return result;
    }
}
